﻿using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.SceneManagement;
using AssetBundles;

public class ResourceManager : BaseManager
{
    void Start() {
        //yield return StartCoroutine(Initialize());
    }

    public IEnumerator Initialize()
    {
        InitializeSourceURL();

        // Initialize AssetBundleManifest which loads the AssetBundleManifest object.
        var request = AssetBundleManager.Initialize();
        if (request != null)
            yield return StartCoroutine(request);
    }

    // Initialize the downloading URL.
    // eg. Development server / iOS ODR / web URL
    void InitializeSourceURL()
    {
        // If ODR is available and enabled, then use it and let Xcode handle download requests.
        #if ENABLE_IOS_ON_DEMAND_RESOURCES
                if (UnityEngine.iOS.OnDemandResources.enabled)
                {
                    AssetBundleManager.SetSourceAssetBundleURL("odr://");
                    return;
                }
        #endif
        #if DEVELOPMENT_BUILD || UNITY_EDITOR //编辑器模式下，设置ab的加载路径
                // With this code, when in-editor or using a development builds: Always use the AssetBundle Server
                // (This is very dependent on the production workflow of the project.
                //      Another approach would be to make this configurable in the standalone player.)
                AssetBundleManager.SetDevelopmentAssetBundleServer();
                return;
#else //打包到目标平台后，去对应的服务器下载资源
                // Use the following code if AssetBundles are embedded in the project for example via StreamingAssets folder etc:
                //暂时改成从工程内的资源释放后存储的本地工程目录内加载，因为现在改成远程服务器下载ab只会在比对版本的时候下载，之后都是从已经更新到最新的本地文件中读取
                //AssetBundleManager.SetSourceAssetBundleURL(MainConfigPath.StreamingAssetsPath());
                AssetBundleManager.SetSourceAssetBundleURL(MainConfigPath.PersistentDataPath());
                // Or customize the URL based on your deployment or configuration
                //AssetBundleManager.SetSourceAssetBundleURL("http://www.MyWebsite/MyAssetBundles");
                return;
#endif
    }



    /// <summary>
    /// 
    /// </summary>
    /// <param name="assetBundleName"></param>
    /// <param name="assetName"></param>
    /// <param name="objType"></param>
    /// <param name="paramDic"></param>
    /// <param name="uiMgrCallBack"></param>
    /// <param name="mediatorCallBack"></param>
    public void LoadAsset(string assetBundleName, string assetName, Type objType, 
        Dictionary<string,object> paramDic,
        Action<UnityEngine.Object,Dictionary<string, object>> uiMgrCallBack)
    {
        StartCoroutine(LoadAssetAsync(assetBundleName, assetName, objType, paramDic,uiMgrCallBack));
    }

    protected IEnumerator LoadAssetAsync(string assetBundleName, string assetName, Type objType,
        Dictionary<string, object> paramDic,
        Action<UnityEngine.Object,Dictionary<string,object>> uiMgrCallBack)
    {
        float startTime = Time.realtimeSinceStartup;
        AssetBundleLoadAssetOperation request = AssetBundleManager.LoadAssetAsync(assetBundleName, assetName,objType);
        if (request == null) {
            Debug.LogError("load ab:" + assetBundleName + "'s asset:" + assetName + " fail");
            yield break;
        }
        yield return StartCoroutine(request);

        UnityEngine.Object prefab = null;
        //Debug.LogError(objType.ToString());
        //prefab = request.GetAsset<UnityEngine.Object>();
        //Debug.LogError(prefab);
        switch (objType.ToString())
        {
            case "UnityEngine.GameObject":
                prefab = request.GetAsset<GameObject>();
                break;
            case "UnityEngine.Sprite":
                prefab = request.GetAsset<Sprite>();
                break;
            case "UnityEngine.AudioClip":
                prefab = request.GetAsset<AudioClip>();
                break;
            case "UnityEngine.TextAsset":
                prefab = request.GetAsset<TextAsset>();
                break;
            case "UnityEngine.Texture2D":
                prefab = request.GetAsset<Texture2D>();
                break;
            case "UnityEngine.Shader":
                prefab = request.GetAsset<Shader>();
                break;
            case "UnityEngine.TerrainData":
                prefab = request.GetAsset<TerrainData>();
                break;
            case "UnityEngine.Material":
                prefab = request.GetAsset<Material>();
                break;
            case "UnityEngine.Font":
                prefab = request.GetAsset<Font>();
                break;
            case "UnityEngine.Object":
                prefab = request.GetAsset<UnityEngine.Object>();
                break;
            case "UnityEngine.AnimationClip":
                prefab = request.GetAsset<AnimationClip>();
                break;
            case "UnityEngine.RuntimeAnimatorController":
                prefab = request.GetAsset<RuntimeAnimatorController>();
                break;
            default:
                Debug.LogError("Un handled asset type:" + objType.ToString());
                break;
        }
        float elapsedTime = Time.realtimeSinceStartup - startTime;
        MainUtil.Log(assetName + (prefab == null ? " was not" : " was") + " loaded successfully in " + elapsedTime + " seconds");

		if (uiMgrCallBack != null) {
			uiMgrCallBack (prefab, paramDic);
		}
    }

    public void LoadScene(string assetBundleName, string sceneName, bool isAdditive, Action sceneLoadedCallBack, Action<Action> sceneMgrCallBack)
    {
        StartCoroutine(LoadSceneAsync(assetBundleName, sceneName, isAdditive, sceneLoadedCallBack, sceneMgrCallBack));
    }

    protected IEnumerator LoadSceneAsync(string assetBundleName, string sceneName, bool isAdditive, Action sceneLoadedCallBack = null, Action<Action> sceneMgrCallBack=null)
    {
        float startTime = Time.realtimeSinceStartup;

        // Load scene from assetBundle.
        AssetBundleLoadOperation request = AssetBundleManager.LoadLevelAsync(assetBundleName, sceneName, isAdditive);
        if (request == null)
            yield break;
        yield return StartCoroutine(request);
        
        float elapsedTime = Time.realtimeSinceStartup - startTime;
        MainUtil.Log("Finished loading scene " + sceneName + " in " + elapsedTime + " seconds");
        if (sceneMgrCallBack != null)
        {
            sceneMgrCallBack(sceneLoadedCallBack);
        }

    }

	public void UnLoadScene(string sceneName){
		SceneManager.sceneUnloaded += (Scene scene) => {
            MainUtil.Log(scene.name.ToString()+ ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>场景卸载成功");
		};
		SceneManager.UnloadSceneAsync (sceneName);
	}
}
